perm filename NTKBAS.MF[MF,ALS] blob
sn#760284 filedate 1984-07-05 generic text, type C, neo UTF8
COMMENT ā VALID 00015 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 % dimensional variables
C00005 00003 % global dimensional variables for characters
C00008 00004 % assignments to global dimensions
C00011 00005 % procedure for drawing character boxes
C00013 00006 % basic procedures for drawing straight strokes
C00016 00007 % procedure for making serifs
C00017 00008 % basic procedures for drawing curved strokes
C00019 00009 % general procedure for making arches
C00021 00010 % procedure for making arches in h,n,m
C00023 00011 % general procedures for drawing bowls
C00026 00012 def cup(suffix z)=
C00029 00013 % procedure for drawing terminals in a,c,s
C00032 00014 % procedure for drawing bowls in b,d,p,q
C00035 00015 % open a display window
C00036 ENDMK
Cā;
% dimensional variables
numeric div,dmm;
div=if mode=proof then 4
elseif mode=sun then 5
elseif mode=smoke then 10
fi;
dmm=(384/25.4)/div; % nominal number of Dover pixels in 1 mm
numeric hmm,vmm, % horizontal and vertical dimensional millimetres
hsmm,vsmm; % stroke-weight
hmm=dmm*expansion;
vmm=dmm;
hsmm=dmm*boldness;
vsmm=vmm; % for the moment
% vertical proportions: originally 36ths of the body size
numeric ascender_height,cap_height,x_height,baseline,descender_length;
ascender_height=29;
cap_height=28;
x_height=20;
baseline=0;
descender_length=-9;
% parameters for drawing
numeric cap_height,vdiv; % size and vertical increment for proofmode drawings
cap_height=round(100 vmm);
vdiv=cap_height/28;
numeric ascender_line,cap_line,x_line,descender_line; % vertical references for grid
ascender_line=round(ascender_height*vdiv);
cap_line=cap_height;
x_line=round(x_height*vdiv);
descender_line=round(descender_length*vdiv);
% global dimensional variables for characters
% basic horizontal dimensions
numeric sidebearing_straight, % sidebearing for straight strokes
sidebearing_curved, % curved
sidebearing_r, % f,j,r
arch_stroke_separation,
bowl_stroke_separation_a, % in bowl of a
bowl_stroke_separation_b, % b,p
bowl_stroke_separation_d, % d,g,q
round_stroke_separation, % round characters
upper_setback_width, % setback width for notches in m,n etc
lower_setback_width, % a,u
% basic vertical dimensions
upper_setback_height,
upper_arch_spring_height,
lower_arch_spring_height_a, % for a,b,p,q
lower_arch_spring_height_d, % b
lower_arch_spring_height_u, % u
a_bar_height,
e_bar_height,
overshoot, % vertical overshoot in arches and round characters
% weight-related dimensions
stroke_weight, % normal weight of straight upright strokes
ascender_weight,
bowl_stroke_weight, % upright strokes in bowls
horizontal_stroke_weight, % straight horizontals
t_bar_weight, % crossbars in f and t
horizontal_curve_weight, % in horizontals of round characters
vertical_curve_weight, % verticals
horizontal_arch_weight,
upper_arch_spring_weight,
lower_arch_spring_weight,
% dimensions of serifs
serif_weight,
lower_external_serif_length,
lower_internal_serif_length,
upper_external_serif_length,
% useful variables for drawing
lhsb,
rhsb,
weight,
width,
slant,
slant_correction;
pair top,bottom,shift;
% assignments to global dimensions
slant=0.25;
% vertical dimensions
overshoot=round(2 vmm);
upper_setback_height=round(0.90[baseline,x_line]);
upper_arch_spring_height=0.89[baseline,x_line];
lower_arch_spring_height_a=0.88[x_line,baseline];
lower_arch_spring_height_b=0.90[x_line,baseline];
lower_arch_spring_height_u=0.86[x_line,baseline];
a_bar_height=round(0.62[baseline,x_line]);
e_bar_height=round(0.59[baseline,x_line]);
% horizontal dimensions
slant_correction=if not (slant_switch) then zero
else: slant*(x_line-baseline)/2
fi;
sidebearing_straight=round(14 hmm-slant_correction);
sidebearing_curved=round(6.5 hmm-slant_correction);
sidebearing_r=round(3.5 hmm-slant_correction);
arch_stroke_separation=round(42 hmm);
bowl_stroke_separation_a=round(43 hmm);
bowl_stroke_separation_b=round(46 hmm);
bowl_stroke_separation_d=round(46 hmm);
round_stroke_separation=round(52 hmm);
upper_setback_width=round(2.5 hmm);
lower_setback_width=round(1.25 hmm);
lower_external_serif_length=round(8.5 hmm);
lower_internal_serif_length=lower_external_serif_length-round(1.5 hmm);
upper_external_serif_length=lower_external_serif_length+round(1.5 hmm);
% weights
stroke_weight=round(13 hsmm);
ascender_weight=round(0.95*stroke_weight);
bowl_stroke_weight=ascender_weight;
vertical_curve_weight=round(1.05*stroke_weight);
horizontal_curve_weight=round(6.75 vsmm);
horizontal_arch_weight=round(8.75 vsmm);
horizontal_stroke_weight=round(6.5 vsmm);
t_bar_weight=horizontal_curve_weight-overshoot;
serif_weight=round(4.5 vsmm);
upper_arch_spring_weight=5.5 vsmm;
lower_arch_spring_weight=upper_arch_spring_weight;
% procedure for drawing character boxes
def widthbox(expr w)=
begingroup save c;pair c[];
def box(suffix s)(text t)=
for i:=t do line(s[i]);endfor
enddef;
def mark(suffix s)(text t)=
% draws crosses at s[i]
begingroup save a,d,p;numeric a;pair d,p;
a=2 dmm; % arm length of cross
for i:=t do
p:=s[i];d:=(a,0);line(p shifted -d..p shifted d);
d:=(0,a);line(p shifted -d..p shifted d);
endfor
endgroup
enddef;
c1=(0,descender_line);
c2=(w,descender_line);
c3=(w,ascender_line);
c4=(0,ascender_line); % outside corners
c5=(0,0);
c6=(w,0); % baseline
c7=(0,x_line);
c8=(w,x_line);
c9=(0,cap_line);
c10=(w,cap_line);
if grid then
begingroup save p;path p[];
p1=c1..c2 & c2..c3 & c3..c4 & c4..c1 & cycle;
p2=c5..c6;
p3=c7..c8;
p4=c9..c10;
box(p)(1,2,3,4)
endgroup
elseif mode=smoke then mark(c)(1,2,3,4,5,6,7,8,9,10)
fi;
if ddisplay then showit fi
endgroup
enddef;
% basic procedures for drawing straight strokes
% all these procedures deliver paths for use with the `draw' command
def vstroke(expr top,bottom,weight,taper,location)=
% draws straight-sided strokes from pair(top) to pair(bottom), to left or right,
% with thickness numeric(weight) at top, tapering by numeric(taper) at bottom
begingroup save p;pair p[];
p1=top;p2=bottom;
p3=p1 shifted (weight,0);p4=p2 shifted (weight-taper,0);
(p1..p2 & p2..p4 & p4..p3 & p3..p1 & cycle)
if location=left then reflected (p1,p2) fi
if slant_switch then slanted slant fi
endgroup
enddef;
def vertical(expr t,b,w,loc)=
% simple application of vstroke
% draws vertically from pair(t) to numeric(b), with zero taper
begingroup save p;pair p;
xpart p=xpart t;
ypart p=b;
vstroke(t,p,w,zero,loc)
endgroup
enddef;
def hstroke(expr start,finish,weight,taper,location)=
% draws straight-sided strokes from pair(start) to pair(finish), with thickness
% numeric(weight) at start, tapering by numeric(taper) at finish
begingroup save p;pair p[];
p1=start;p2=finish;
p11=offset(p1,p2,weight,right);
p12=offset(p2,p1,(weight-taper),left);
(p1..p2 & p2..p12 & p12..p11 & p11..p1 & cycle)
if ((location=above) or (location=left)) then reflected(p1,p2) fi
if slant_switch then slanted slant fi
endgroup
enddef;
% procedure for making serifs
% makes slab serifs of weight serif_weight
def serif(expr length,direction,position)=
begingroup save l,w;numeric l,w;
l=ypart position;w=l-serif_weight;
if (l=baseline) or (l=descender_line) then w:=l+serif_weight
fi;
vertical(position,w,length,direction)
endgroup
enddef;
% basic procedures for drawing curved strokes
% these procedures draw through points in z[], which are numbered according
% to a standard convention
% z1 is the start point (on the outside of the curve)
% z2 first horizontal (or vertical) tangent
% z3 45-degree tangent point
% z4 vertical (or horizontal) tangent
% z5 second 45-degree tangent point
% z6 horizontal (or vetrical) tangent
% z7 outside finish point
% z8 outer start slope point
% z9 finish
% points z11 - z19 are the corresponding points on the inside of the curve
% curves can go right (like the bowl of small p) with z1 on the left
% left d right
% up (like the top of small e)
% down bottom
% the latter two kinds always have point z1 on the left
% procedures like `arch' that don't use all the points skip those that
% aren't appropriate
% general procedure for making arches
def arch(suffix z)(expr start_weight)=
begingroup save a,b,d,p;numeric a,b;pair d[];path p[];
% test for directions in arch
a=if x4>x1 then 1
else: -1
fi;
b=if y2>y7 then -1
else: 1
fi;
% set directions
d1=z8-z1;
d2=(a,0);
d3=(a,b);
d4=(0,b);
d11=z18-z11;
d28=if ((a=1) and (b=-1)) or ((a=-1) and (b=1)) then right
else: left
fi;
% set inner start point
if unknown(y11) then
z28=offset(z1,z8,start_weight,d28);
y11=simy(z28,z18,x11)
fi;
% label points
if grid and labels then
labelpos(1,2,3,4,7,8,11,12,13,14,17,18)
fi;
(z1{d1}..z2{d2}..z3{d3}..z4{d4}..z7
& z7..z17
& reverse(z11{d11}..z12{d2}..z13{d3}..z14{d4}..z17)
& z11..z1
& cycle) % final path
if slant_switch then slanted slant fi
endgroup
enddef;
% procedure for making arches in h,n,m
def n_arch(expr start_point,
inner_edge,
inner_width
)=
begingroup save d,x,y;numeric x[],y[];pair d[];
z1=start_point;
x2=0.57[x1,x4];
x3=0.91[x1,x4];
x4=x14+stroke_weight;
x7=x4;
x8=x2;
x11=inner_edge;
x12=0.67[x11,x14];
x13=0.94[x11,x14];
x14=x1+inner_width;
x17=x14;
x18=x12;
y2=x_line+overshoot;
y3=0.94[y7,y2];
y4=0.75[y7,y2];
y7=baseline;
y8=1.14[y7,y2];
y12=y2-horizontal_arch_weight;
y13=0.95[y7,y12];
y14=0.85[y7,y12];
y17=y7;
y18=1.10[y7,y12];
arch(z)(upper_arch_spring_weight)
endgroup
enddef;
% general procedures for drawing bowls
def bowl(suffix z)(expr start_weight,end_weight)=
% draws through points in z[], with standard numbering convention
% needs x11 and x17; calculates y11 and y17 if not given them
begingroup save a,b,d,p;numeric a,b;pair d[];path p[];
% set directions in path
a=if x4>x1 then 1
elseif x4<x1 then -1
else: 0;errmessage("Left and right sides of bowl coincide")
fi;
b=if y2>y6 then -1
elseif y2<y6 then 1
else: 0;errmessage("Top and bottom of bowl coincide")
fi;
d1=z8-z1;
d2=(a,0);
d3=(a,b);
d4=(0,b);
d5=(-a,b);
d6=(-a,0);
d7=z7-z9;
d28=(a,0);
d29=(-a,0);
% find inner start and finish points
if unknown(y11) then
z28=offset(z1,z8,start_weight,d28);
y11=simy(z28,z18,x11)
fi;
if unknown(y17) then
z29=offset(z7,z9,end_weight,d29);
y17=simy(z29,z19,x11)
fi;
% set directions at inner start and finish points
d11=z18-z11;
d17=z17-z19;
if grid and labels then
labelpos(1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19)
fi;
p1=z1{d1}..z2{d2}..z3{d3}..z4{d4}..
z5{d5}..z6{d6}..z7{d7}; % outside of bowl
p2=z11{d11}..z12{d2}..
z13{d3}..
tension 1.5 and 1..
z14{d4}..
tension 1 and 1.5..
z15{d5}..
z16{d6}..
z17{d17}; % inside
(p1 & z7..z17 & reverse(p2) & z11..z1 & cycle)
if slant_switch then slanted slant fi % final path
endgroup
enddef;
def cup(suffix z)=
% draws through points in z[], with standard numbering convention
% needs z11 and z17
begingroup save a,b,d,p;numeric a,b;pair d[];path p[];
% set directions in path
a=if x7>x1 then 1
elseif x7<x1 then -1
else: 0;errmessage("Left and right sides of cup coincide")
fi;
b=if y4>y1 then 1
elseif y4<y1 then -1
else: 0;errmessage("Top and bottom of cup coincide")
fi;
d1=z8-z1;
d2=(0,b);
d3=(a,b);
d4=(a,0);
d5=(a,-b);
d6=(0,-b);
d7=z7-z9;
d11=z18-z11;
d17=z17-z19;
if grid and labels then
labelpos(1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19);
fi;
p1=if known(z2) then z1{d1}..z2{d2}
else: z1{d1}
fi..
z3{d3}..z4{d4}..
if known(z6) then z5{d5}..z6{d6}
else: z5{d5}
fi..
z7{d7}; % outside of bowl
p2=if known(z12) then z11{d11}..z12{d2}
else: z11{d11}
fi..
z13{d3}..
tension 1.5 and 1..
z14{d4}..
tension 1 and 1.5..
if known(z16) then z15{d5}..z16{d6}
else: z15{d5}
fi..
z17{d17}; % inside
(p1 & z7..z17 & reverse(p2) & z11..z1 & cycle)
if slant_switch then slanted slant fi % final path
endgroup
enddef;
% procedure for drawing terminals in a,c,s
def a_term(suffix z)=
% draws upper terminals in a,c,s; lower terminal in s
% outside is like arch; inside like cup
% outside skips z2 and z3 in standard numbering scheme
begingroup save a,b,d,p;numeric a,b;pair d[];path p[];
% set directions
a=if x7>x1 then 1
elseif x7<x1 then -1
else: 0;errmessage("Left and right sides of curve coincide")
fi;
b=if y4>y1 then 1
elseif y4<y1 then -1
else: 0;errmessage("Top and bottom of curve coincide")
fi;
d1=z8-z1;
d2=(0,b);
d3=(a,b);
d4=(a,0);
d5=(a,-b);
d6=(0,-b);
d7=z7-z6;
d11=z18-z11;
d17=z17-z16;
% add corner point at terminal
x21=x1;
y21=y11;
if grid and labels then
labelpos(1,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,21);
fi;
p1=z1{d1}..z4{d4}..z5{d5}..z6{d6}..z7{d7}; % outside of curve
p2=if known(z12) then z11{d11}..z12{d2}
else: z11{d11}
fi..
z13{d3}..
tension 1.5 and 1..
z14{d4}..
tension 1 and 1.5..
if known(z16) then z15{d5}..z16{d6}
else: z15{d5}
fi..
z17{d17}; % inside
(p1 & z7..z17 & reverse(p2) & z11..z21 & z21..z1 & cycle)
if slant_switch then slanted slant fi % final path
endgroup
enddef;
% procedure for drawing bowls in b,d,p,q
def p_bowl(expr start_point,
inner_edge,
inner_width,
bottom_edge,
end_height,
skew
)=
begingroup save x,y;numeric x[],y[];
z1=start_point;
x2=0.56[x1,x4]; % outer upper horizontal tangent x
x4=x14+vertical_curve_weight; % right-hand edge
x5=0.80[x11,x4]-skew; % lower 45-degree point
x6=0.40[x11,x4]-skew; % horizontal tangent
x7=x1; % finish point
x11=inner_edge; % inner left-hand edge
x12=0.51[x11,x14]; % upper horizontal tangent x
x14=x1+inner_width; % right-hand edge
x15=x13-skew; % lower 45-degree point
x16=x12-skew; % horizontal tangent
x17=x11; % finish point
y2=x_line+overshoot; % outer upper horizontal tangent y
y4=y14=0.5[y2,y6]; % vertical tangents
y5=0.90[y2,y6]; % outer lower 45-degree point
y6=bottom_edge; % lower vertical reference
y7=end_height; % finish point
y12=y2-horizontal_arch_weight; % inner upper horizontal tangent y
y15=0.91[y12,y16]; % lower 45-degree point
y16=y6+horizontal_curve_weight; % horizontal tangent
z3=(0.82[x11,x4],0.94[y6,y2]); % outer upper 45-degree point
z13=(0.82[x11,x14],0.95[y16,y12]); % inner
z8=(x2,1.1[y6,y2]); % outer upper slope point
z9=(x6,1.1[y2,y6]); % lower
z18=(x12,1.06[y16,y12]); % inner upper start slope point
z19=(x16,1.13[y12,y16]); % lower
bowl(z)(upper_arch_spring_weight,lower_arch_spring_weight)
endgroup
enddef;
% open a display window
numeric screen_width,screen_depth;
screen_width=480;screen_depth=400;
pair top_left,window_left,window_right;
top_left=(-10,ascender_line); % this is in Metafont coordinates, with
% the origin in the usual place
window_left=(0,0);
window_right=(screen_depth,screen_width); % these are in screen coordinates, with
% the origin at the top left of the screen
% and the first coordinate giving the depth
grid=if (mode=proof) or (mode=sun) then yes
else: no
fi;
if ddisplay then
openwindow 1 from window_left to window_right at top_left
fi;